/** 
 * @defgroup sensor sensor
 * sensor (input) related routines
 * @{
 */

#include <X11/X.h>
#include <string.h>
#include "main.h"
#include "prefs.h"
#include "output.h"
#include "gui.h"
#include "source.h"
#include "warp.h"
#include "thresh.h"
#include "sensor.h"


static struct sensor *sensor_get_n(int n);
static int sensor_listlen();
static struct sensor *sensor_new(char *name);
void sensor_free(struct sensor *s);


/** local info structure */
static struct Sensor
{
    struct sensor *current_sensor;
}sensor_cfg;

/********************* getter/setter for local variables *********************/
/**
 * get current sensor structure
 * @result struct sensor *sensor or NULL
 */
struct sensor *sensor_get()
{
    if(!(sensor_cfg.current_sensor))
        _VERBOSE3 printf("%s(): returned NULL pointer!\n", __func__);
    return sensor_cfg.current_sensor;
}


/**
 * set current sensor
 * @param sensor - current sensor
 */
void sensor_set(struct sensor *s)
{
    sensor_cfg.current_sensor = s;
}


 
 
/************************** GTK-Callbacks **************************/
/**
 * path of out_program changed
 */
gboolean cb_out_program_changed(GtkWidget * widget)
{
    
    if(sensor_get())
    {
        free(sensor_get()->out_program);
        
        sensor_get()->out_program =
                strdup((char *) gtk_entry_get_text(GTK_ENTRY(widget)));
    }
    
    return FALSE;
}

/**
 * kind of output changed in "Output" menu, make visible... 
 */
gboolean cb_sensor_op_changed(GtkWidget * widget)
{
    int type;

    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        type = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

        /*
         * set output-type 
         */
        sensor_get()->out_type = type;
        
        /*
         * switch output-menu 
         */
        output_set_type(sensor_get()->out_type);
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    return FALSE;
}


/**
 * key for keyboard-output changed
 */
gboolean cb_sensor_key_changed(GtkWidget *widget)
{
    sensor_get()->out_key = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
    
    return FALSE;
}

/**
 * different sensor selected 
 */
gboolean cb_sensor_changed(GtkWidget * widget)
{
    struct sensor *s;

    
    _VERBOSE2 printf("%s()\n", __func__);

    
    /*
     * get newly selected sensor 
     */
    if((s = sensor_get_n(gtk_combo_box_get_active(GTK_COMBO_BOX(widget)))))
    {
        /* new sensor? */
        if(s != (sensor_get()))
        {
            /* set new current-source */
            sensor_set(s);
            
            sensor_gui_update();
        }
    }
    
    return FALSE;
}
        
/**
 * rename sensor-button pressed
 */
gboolean cb_sensor_rename(GtkWidget * widget)
{
    struct sensor *s = sensor_get();
        
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(s)
    {
        /*
         * set new name 
         */
        gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(gui_get_xml(),
                                                          "entry_sensor_rename_new")),
                           (gchar *) s->name);

        /*
         * set old name 
         */
        gtk_label_set_text(GTK_LABEL(glade_xml_get_widget(gui_get_xml(),
                                                          "label_sensor_rename_old")),
                           (gchar *) s->name);

        /*
         * select everything & activate edit-widget 
         */
        gtk_widget_activate(glade_xml_get_widget(gui_get_xml(),
                                                 "entry_sensor_rename_new"));

        /*
         * show name-request window 
         */
        gtk_widget_show(glade_xml_get_widget
                        (gui_get_xml(), "dialog_sensor_rename"));
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    
    return FALSE;
}

/**
 * sensor-renaming has been canceled
 */
gboolean cb_sensor_rename_cancel_but(GtkWidget * widget)
{

    _VERBOSE2 printf("%s()\n", __func__);
    
    /*
     * hide name-request window 
     */
    gtk_widget_hide(glade_xml_get_widget
                    (gui_get_xml(), "dialog_sensor_rename"));

    return FALSE;
}

/**
 * sensor-renaming has been canceled
 */
gboolean cb_sensor_rename_cancel_del(GtkWidget * widget, GdkEvent * event)
{

    _VERBOSE2 printf("%s()\n", __func__);
    
    /*
     * hide name-request window 
     */
    gtk_widget_hide(glade_xml_get_widget
                    (gui_get_xml(), "dialog_sensor_rename"));

    return TRUE;
}

/**
 * "OK"-Button in rename-dialog pressed, set new name 
 */
gboolean cb_sensor_rename_set(GtkWidget * widget)
{
    struct sensor *s = sensor_get();
    const gchar *new_name;

    _VERBOSE2 printf("%s()\n", __func__);
    
    if(s) 
    {

        /*
         * get name 
         */
        new_name = gtk_entry_get_text(GTK_ENTRY
                                      (glade_xml_get_widget
                                       (gui_get_xml(),
                                        "entry_sensor_rename_new")));
        /*
         * validate name 
         */

        /* free old name */
        xmlFree(s->name);
        
        /*
         * set name 
         */
        s->name = xmlStrdup((xmlChar *) new_name);

        /*
         * refresh sensor-menu 
         */
        sensor_gui_update_pulldown();

        /*
         * close window 
         */
        cb_sensor_rename_cancel_but(NULL);

        _VERBOSE1 printf("%s(): renamed to \"%s\"\n",
                         __func__, new_name);
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    return FALSE;
}

/**
 * add new-sensor button pressed 
 */
gboolean cb_sensor_add(GtkWidget * widget)
{
    struct sensor *s;
    char tmpstring[255];

    
    _VERBOSE2 printf("%s()\n", __func__);
    
    /*
     * build new name 
     */
    snprintf((char *) &tmpstring, 254, "Sensor-%d", sensor_listlen() + 1);
    
    /* init new sensor structure */
    if((s = sensor_new((char *) &tmpstring)))
    {
        /* append sensor to this source */
        sensor_append(src_get()->first_sensor, s);
        
        /* refresh GUI */
        sensor_gui_update_pulldown();
        sensor_gui_update();
    }
    
    return FALSE;
}

/**
 * remove sensor-button pressed
 */
gboolean cb_sensor_remove(GtkWidget * widget)
{
    int pos;
    struct sensor *p, *c, *n;
        
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    pos = gtk_combo_box_get_active(GTK_COMBO_BOX(
            glade_xml_get_widget(gui_get_xml(), "combobox_sensors")));
    c = sensor_get_n(pos);
    p = sensor_get_n(pos-1);
    n = sensor_get_n(pos+1);
    
    if(n || p)
    {
        if(p)
            p->next_sensor = n;
        else
            src_get()->first_sensor = n;
        
        
        if(n)
        {
            sensor_set(n);
        }
        else
        {
            sensor_set(p);
            pos--;
        }
     
        sensor_free(c);
        sensor_gui_update_pulldown();
        sensor_gui_update();
        
        gtk_combo_box_set_active(GTK_COMBO_BOX
                                     (glade_xml_get_widget
                                      (gui_get_xml(),
                                       "combobox_sensors")), pos);
    }
    else
    {
        gui_dialog("Last sensor can't be deleted");
    }
    
    return FALSE;
}




/**
 * append copy of current sensor
 */
gboolean cb_sensor_copy(GtkWidget * widget)
{
    struct sensor *new, *current;
    char tmp[1024];
    
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if((current = sensor_get()))
    {
        if((new = calloc(1, sizeof(struct sensor))))
        {
            /*
             * copy sensor 
             */
            memcpy(new, current, sizeof(struct sensor));

            /*
             * rebuild name 
             */
            snprintf((char *) &tmp, 1023, "%s (%d)",
                     current->name, sensor_listlen());
                
            new->name = xmlStrdup((xmlChar *) &tmp);
            
            if(new->out_program)
                new->out_program = strdup(new->out_program);
            
            
            /*
             * append sensor 
             */
            new->next_sensor = NULL;
                    
            src_get()->first_sensor =
                        sensor_append(src_get()->first_sensor, new);
            
            sensor_gui_update_pulldown();
            //sensor_gui_update();
        
        }
        
    }
    
    return FALSE;
}

/**
 * width of virtual display changed
 */
gboolean cb_out_width_changed(GtkWidget * widget)
{
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get()) {
        sensor_get()->out_width =
            (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    return TRUE;
}

/**
 * height of virtual display changed
 */
gboolean cb_out_height_changed(GtkWidget * widget)
{
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        sensor_get()->out_height =
            (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    return TRUE;
}

/**
 * callback when user changed the on-delay
 * @param widget - this widget
 * @result gboolean for gtk
 */
gboolean cb_out_ondelay_changed(GtkWidget * widget)
{
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        sensor_get()->ondelay =
            (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    
    return TRUE;
}

/**
 * callback when user changed the off-delay
 * @param widget - this widget
 * @result gboolean for gtk
 */
gboolean cb_out_offdelay_changed(GtkWidget * widget)
{
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        sensor_get()->offdelay =
            (int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
    }
    else
    {
        _ERROR printf("%s(): NULL-pointer received!\n", __func__);
    }
    
    return TRUE;
}

/**
 * callback when key-delay changed
 */
gboolean cb_out_repeatDelay_changed(GtkWidget *widget)
{
    
    sensor_get()->repeat_delay =
                    gtk_spin_button_get_value(GTK_SPIN_BUTTON(widget));
    
    return FALSE;
}

/**
 * mouse-button 1 output switched on/off by user
 */
void cb_but_toggle1(GtkWidget *widget, gpointer data)
{
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
        {
            sensor_get()->buttonmask |= Button1Mask;
        
        } else 
        {
            sensor_get()->buttonmask &= (sensor_get()->buttonmask^Button1Mask);
        }
    }
}

/**
 * mouse-button 2 output switched on/off by user
 */
void cb_but_toggle2(GtkWidget *widget, gpointer data)
{
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
        {
            sensor_get()->buttonmask |= Button2Mask;
        
        } else 
        {
            sensor_get()->buttonmask &= (sensor_get()->buttonmask^Button2Mask);
        }
    }
}

/**
 * mouse-button 3 output switched on/off by user
 */
void cb_but_toggle3(GtkWidget *widget, gpointer data)
{
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
        {
            sensor_get()->buttonmask |= Button3Mask;
        
        } else 
        {
            sensor_get()->buttonmask &= (sensor_get()->buttonmask^Button3Mask);
        }
    }
}
/**
 * mouse-button 4 output switched on/off by user
 */
void cb_but_toggle4(GtkWidget *widget, gpointer data)
{
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
        {
            sensor_get()->buttonmask |= Button4Mask;
        
        } else 
        {
            sensor_get()->buttonmask &= (sensor_get()->buttonmask^Button4Mask);
        }
    }
}

/**
 * mouse-button 5 output switched on/off by user
 */
void cb_but_toggle5(GtkWidget *widget, gpointer data)
{
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(sensor_get())
    {
        
        if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))) 
        {
            sensor_get()->buttonmask |= Button5Mask;
        
        } else 
        {
            sensor_get()->buttonmask &= (sensor_get()->buttonmask^Button5Mask);
        }
    }
}


/************************** Module **************************/
/**
 * append sensor to list of sensors
 */
struct sensor *sensor_append(struct sensor *first_sensor,
                             struct sensor *this_sensor)
{
    struct sensor *tmp_sensor;

    _VERBOSE2 printf("append_sensor(): \"%s\"\n", this_sensor->name);
    /*
     * append sensor 
     */
    if(first_sensor) 
    {
        tmp_sensor = first_sensor;
        while (tmp_sensor->next_sensor)
            tmp_sensor = tmp_sensor->next_sensor;
        tmp_sensor->next_sensor = this_sensor;
        return first_sensor;
    }
    else
        return this_sensor;
}

/**
 * initialize sensor from xmlNode and append to list of sensors
 * returns first element of the sensor-list 
 */
struct sensor *sensor_append_from_xml(struct sensor *first_sensor, xmlNode * node)
{
    xmlNode *tmp, *tmp2;
    char *tmp_char;
    struct sensor *new;

    /*
     * allocate new-sensor 
     */
    if((new = calloc(1, sizeof(struct sensor)))) {
        /*
         * get name 
         */
        new->name = xmlGetProp(node, (xmlChar *) "name");
        
        /** get delay */
        tmp_char = (char *) xmlGetProp(node, (xmlChar *) "on_delay");
        if(tmp_char) new->ondelay = atoi(tmp_char);
        else    new->ondelay = 0;
        tmp_char = (char *) xmlGetProp(node, (xmlChar *) "off_delay");
        if(tmp_char) new->offdelay = atoi(tmp_char);
        else    new->offdelay = 0;
        tmp_char = (char *) xmlGetProp(node, (xmlChar *) "repeat_delay");
        if(tmp_char) new->repeat_delay = atoi(tmp_char);
        else    new->repeat_delay = 0;
            
        /*
         * default dimensions 
         */
        new->out_width = 720;
        new->out_height = 576;

        /*
         * get output node 
         */
        if((tmp = prefs_xmlNode_find("output", prefs_get_xmlDoc(), node)))
        {
            /*
             * OUT_TYPE_MOUSE 
             */
            if(xmlStrcmp(xmlGetProp(tmp, (xmlChar *) "type"),
                (xmlChar *) "mouse") == 0) 
            {
                new->out_type = OUT_TYPE_MOUSE;

                /*
                 * get mouse-node 
                 */
                if((tmp2 = prefs_xmlNode_find("mouse", prefs_get_xmlDoc(), tmp)))
                {
                    tmp_char = (char *) xmlGetProp(tmp2, (xmlChar *) "width");
                    if(tmp_char)
                        new->out_width = atoi(tmp_char);
                    tmp_char =
                        (char *) xmlGetProp(tmp2, (xmlChar *) "height");
                    if(tmp_char)
                        new->out_height = atoi(tmp_char);
                    tmp_char =
                        (char *) xmlGetProp(tmp2, (xmlChar *) "buttonmask");
                    if(tmp_char)
                        new->buttonmask = atoi(tmp_char);
                }
            }

            /*
             * OUT_TYPE_KEY 
             */
            if(xmlStrcmp(xmlGetProp(tmp, (xmlChar *) "type"),
                (xmlChar *) "keyboard") == 0) 
            {
                new->out_type = OUT_TYPE_KEY;

                /*
                 * get keyboard node 
                 */
                if((tmp2 = prefs_xmlNode_find("keyboard", prefs_get_xmlDoc(), tmp)))
                {
                    /* get key */
                    tmp_char =
                        (char *) xmlGetProp(tmp2, (xmlChar *) "menu-entry");
                    if(tmp_char)
                        new->out_key = atoi(tmp_char);
                    

                }
                
                
                
            }

            
            /*
             * OUT_TYPE_EXE
             */
            if(xmlStrcmp(xmlGetProp(tmp, (xmlChar *) "type"),
                (xmlChar *) "execute") == 0)
            {
                new->out_type = OUT_TYPE_EXE;
                
                /*
                 * get program node
                 */
                if((tmp2 = prefs_xmlNode_find("program", prefs_get_xmlDoc(), tmp)))
                {
                    if((tmp_char = (char *) xmlGetProp(tmp2, (xmlChar *) "path")))
                    {
                        new->out_program = strdup(tmp_char);
                    }
                    
                }
            }
            
            /*
             * get color node 
             */
            if((tmp = prefs_xmlNode_find("color", prefs_get_xmlDoc(), node)))
            {
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "threshold");
                if(tmp_char)
                    new->thr_threshold = strtod(tmp_char, NULL);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "R");
                if(tmp_char)
                    new->thr_R = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "G");
                if(tmp_char)
                    new->thr_G = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "B");
                if(tmp_char)
                    new->thr_B = atoi(tmp_char);
            }

            /*
             * get field node 
             */
            if((tmp = prefs_xmlNode_find("field", prefs_get_xmlDoc(), node)))
            {
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "x1");
                if(tmp_char)
                    new->wrp_x1 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "x2");
                if(tmp_char)
                    new->wrp_x2 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "x3");
                if(tmp_char)
                    new->wrp_x3 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "x4");
                if(tmp_char)
                    new->wrp_x4 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "y1");
                if(tmp_char)
                    new->wrp_y1 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "y2");
                if(tmp_char)
                    new->wrp_y2 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "y3");
                if(tmp_char)
                    new->wrp_y3 = atoi(tmp_char);
                tmp_char = (char *) xmlGetProp(tmp, (xmlChar *) "y4");
                if(tmp_char)
                    new->wrp_y4 = atoi(tmp_char);
            }

        }

    }

    /*
     * append to list 
     */
    return sensor_append(first_sensor, new);

}

/**
 * free sensor structure
 */
void sensor_free(struct sensor *s)
{
    if(s)
    {
        _VERBOSE5 printf("%s(): %s\n", __func__, s->name);
        xmlFree(s->name);
        free(s->out_program);
        free(s);           
    }
}
/**
 * free one sensor-structure
 */
void sensor_list_free(struct sensor *sensors)
{
    struct sensor *current_sensor, *next_sensor;

    if(sensors) {
        _VERBOSE2 printf("free_sensors()\n");
        current_sensor = sensors;

        while (current_sensor) 
        {
            next_sensor = current_sensor->next_sensor;
            sensor_free(current_sensor);
            current_sensor = next_sensor;
        }
    }
}





/**
 * build pulldown-menu for all sensors 
 */
void sensor_pulldown_refresh()
{
    GtkWidget *pulldown;
    struct sensor *current_sensor;
    char temp[255];
    int count, id = 0;

    _VERBOSE2 printf("%s()\n", __func__);

    if(!(pulldown =
         glade_xml_get_widget(gui_get_xml(), "combobox_sensors")))
          return;

    /*
     * free old menu 
     */
    for(count =
        gtk_tree_model_iter_n_children(gtk_combo_box_get_model
                                       (GTK_COMBO_BOX(pulldown)), NULL);
        count > 0; count--) {

        /*
         * remove first entry 
         */
        gtk_combo_box_remove_text(GTK_COMBO_BOX(pulldown), 0);
    }

    /*
     * get widget 
     */
    if(src_get() && src_get()->first_sensor) {

        /*
         * append all sensors 
         */
        for(current_sensor = src_get()->first_sensor;
            current_sensor; current_sensor = current_sensor->next_sensor) {

            /*
             * build up some name if necessary
             */
            if(!current_sensor->name) {
                snprintf((char *) &temp, 255, "Sensor #%d", id);
                current_sensor->name = (xmlChar *) strdup((char *) &temp);
            }

            /*
             * append name 
             */
            gtk_combo_box_append_text(GTK_COMBO_BOX(pulldown),
                                      (gchar *) current_sensor->name);

            /*
             * set as current sensor if it's the right sensor 
             */
            if(current_sensor == sensor_get()) {
                gtk_combo_box_set_active(GTK_COMBO_BOX(pulldown), id);
            }

            /*
             * sensor counter 
             */
            id++;
        }
    }
}



/**
 * initialize sensor-module
 */
int sensor_init()
{
    /* clear structure */
    memset(&sensor_cfg, 0, sizeof(struct Sensor));
   
    return 0;
}
/**
 * amount of sensors in current source
 */
int sensor_listlen()
{
    int result = 0;
    struct sensor *current_sensor;
        
    if((current_sensor = sensor_get())) {

        while (current_sensor) {
            result++;
            current_sensor = current_sensor->next_sensor;
        }
    }
    
    return result;
}


/**
 * gets nth sensor of current sources list
 */
struct sensor *sensor_get_n(int n)
{
    struct sensor *s;
    int count = 0;
    
    if(n < 0) 
        return NULL;
    
    for(s = src_get()->first_sensor; s; s = s->next_sensor)
    {
        if(count == n)
            break;
        
        count++;
    }
    
    if(count == n)
        return s;
    else
        return NULL;
}

/**
 * fresh new sensor structure
 */
struct sensor *sensor_new(char *name)
{
    struct sensor *s = NULL;
        
    _VERBOSE2 printf("%s()\n", __func__);
    
    if(!(s = calloc(1, sizeof(struct sensor))))
    {
        _ERROR printf("%s() failed!\n", __func__);
    }
    
    return s;
}
/**
 * update combobox listing sensors
 */
void sensor_gui_update_pulldown()
{
    GtkWidget *pulldown;
    struct sensor *s;
    char temp[255];
    int count, id = 0;

    
    _VERBOSE2 printf("%s()\n", __func__);
    
    /*
     * get widget 
     */
    if(sensor_get() &&
       (pulldown =
        glade_xml_get_widget(gui_get_xml(), "combobox_sensors")))
    {

        /*
         * free old menu 
         */
        for(count =
            gtk_tree_model_iter_n_children(gtk_combo_box_get_model
                                           (GTK_COMBO_BOX(pulldown)), NULL);
            count > 0; count--) {

            /*
             * remove first entry 
             */
            gtk_combo_box_remove_text(GTK_COMBO_BOX(pulldown), 0);
        }

        /*
         * get first_sensor
         */
        for(s = src_get()->first_sensor; s; s = s->next_sensor) 
        {

            /*
             * build up some name if necessary
             */
            if(!s->name) {
                snprintf((char *) &temp, 255, "Sensor #%d", id);
                s->name = (xmlChar *) strdup((char *) &temp);
            }

            /*
             * append name 
             */
            gtk_combo_box_append_text(GTK_COMBO_BOX(pulldown),
                                      (gchar *) s->name);

            /*
             * set as current source if it's the right sensor 
             */
            if(s == sensor_get()) 
            {
                gtk_combo_box_set_active(GTK_COMBO_BOX(pulldown), id);
            }

            /*
             * source counter 
             */
            id++;
        }

    }
}

/**
 * update sensor-related GUI
 */
void sensor_gui_update()
{
    GtkWidget *widget;
    
    
     _VERBOSE2 printf("%s()\n", __func__);
    
    /*
     * set warp coordinates 
     */
    src_set_updateWarpGui(TRUE);
    thresh_gui_update();
    

    
    /*
     * output width & height 
     */
    gtk_spin_button_set_value(GTK_SPIN_BUTTON
                              (glade_xml_get_widget
                               (gui_get_xml(),
                                "spinbutton_out_width")),
                              (gdouble) sensor_get()->out_width);
    
    gtk_spin_button_set_value(GTK_SPIN_BUTTON
                              (glade_xml_get_widget
                               (gui_get_xml(),
                                "spinbutton_out_height")),
                              (gdouble) sensor_get()-> out_height);
                              
    /*
     * update output type 
     */
    gtk_combo_box_set_active(GTK_COMBO_BOX
                             (glade_xml_get_widget
                              (gui_get_xml(), "combobox_out_type")), 
                              sensor_get()->out_type);


        
    /* hide all output-types */
    gtk_widget_hide(glade_xml_get_widget
                    (gui_get_xml(), "frame_out_mouse"));
    gtk_widget_hide(glade_xml_get_widget(gui_get_xml(), "frame_out_key"));
    gtk_widget_hide(glade_xml_get_widget(gui_get_xml(), "frame_out_tcp"));
    gtk_widget_hide(glade_xml_get_widget(gui_get_xml(), "frame_out_launch"));

    /* reset widget */
    widget = NULL;
    _VERBOSE2 printf("%s(): showing output %d\n", 
                        __func__, sensor_get()->out_type);

    
    switch (sensor_get()->out_type) 
    {
        
        
        /* mouse output */
        case OUT_TYPE_MOUSE:
            widget = glade_xml_get_widget(gui_get_xml(), "frame_out_mouse");
            
            /* set button-checkboxes */
            if(sensor_get())
            {
                if(sensor_get()->buttonmask & Button1Mask)
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button1")), TRUE);
                else
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button1")), FALSE);
                
                if(sensor_get()->buttonmask & Button2Mask)
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button2")), TRUE);
                else
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button2")), FALSE);
                
                if(sensor_get()->buttonmask & Button3Mask)
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button3")), TRUE);
                else
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button3")), FALSE);
                
                if(sensor_get()->buttonmask & Button4Mask)
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button4")), TRUE);
                else
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button4")), FALSE);
                
                if(sensor_get()->buttonmask & Button5Mask)
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button5")), TRUE);
                else
                    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
                        glade_xml_get_widget(
                            gui_get_xml(), "checkbutton_button5")), FALSE);
            }
            break;

        
        /* keyboard output */
        case OUT_TYPE_KEY:
            widget = glade_xml_get_widget(gui_get_xml(), "frame_out_key");
        
            /* show key of current sensor */
            gtk_combo_box_set_active(GTK_COMBO_BOX
                                     (glade_xml_get_widget
                                      (gui_get_xml(), "combobox_out_key")),
                                         sensor_get()->out_key);
            break;

        
        /* tcp-ip output */
        case OUT_TYPE_TCP:
            widget = glade_xml_get_widget(gui_get_xml(), "frame_out_tcp");
            break;
        
        
        /* launch executable */
        case OUT_TYPE_EXE:
            widget = glade_xml_get_widget(gui_get_xml(), "frame_out_launch");
            
            /* set path */
            if(sensor_get()->out_program)
            {
                if(sensor_get()->out_program)
                    gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(
                        gui_get_xml(), "entry_out_exe")), sensor_get()->out_program);
                else
                    gtk_entry_set_text(GTK_ENTRY(glade_xml_get_widget(
                        gui_get_xml(), "entry_out_exe")), "");
            }
            break;
        
        default:
            _ERROR printf("%s(): unknown output-type!\n", __func__);
            break;
    }

    gtk_widget_show(widget);
    
    /* update delay */
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(
                glade_xml_get_widget(gui_get_xml(), "spinbutton_out_ondelay")),
                (gdouble) (sensor_get()->ondelay));
    
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(
                glade_xml_get_widget(gui_get_xml(), "spinbutton_out_offdelay")),
                (gdouble) (sensor_get()->offdelay));
    
    gtk_spin_button_set_value(GTK_SPIN_BUTTON(
                glade_xml_get_widget(gui_get_xml(), "spinbutton_out_repeat")), 
                (gdouble) sensor_get()->repeat_delay);
}

/**
 * initialize GUI
 */
int sensor_gui_init()
{
    _VERBOSE2 printf("%s()\n", __func__);
    
    
    
    /*g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "button_sensor_copy")), "clicked",
                     G_CALLBACK(cb_sensor_copy), NULL);
    
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "button_sensor_rename")), "clicked",
                     G_CALLBACK(cb_sensor_rename), NULL);

    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "button_sensor_rename_cancel")),
                     "clicked", G_CALLBACK(cb_sensor_rename_cancel_but),
                     NULL);

    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "button_sensor_rename_ok")),
                     "clicked", G_CALLBACK(cb_sensor_rename_set), NULL);

    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "dialog_sensor_rename")),
                     "delete-event", G_CALLBACK(cb_sensor_rename_cancel_del),
                     NULL);
                     
    g_signal_connect(G_OBJECT
                         (glade_xml_get_widget
                          (gui_get_xml(), "combobox_out_key")), "changed",
                         G_CALLBACK(cb_sensor_key_changed), NULL);
    
    g_signal_connect(G_OBJECT
                         (glade_xml_get_widget
                          (gui_get_xml(), "combobox_sensors")), "changed",
                         G_CALLBACK(cb_sensor_changed), NULL);
    
    g_signal_connect(G_OBJECT
                         (glade_xml_get_widget
                          (gui_get_xml(), "combobox_out_type")), "changed",
                         G_CALLBACK(cb_sensor_op_changed), NULL);
        
    
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "spinbutton_out_key")),
                     "value-changed", G_CALLBACK(cb_out_keydelay_changed), NULL);
                     
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "spinbutton_out_width")),
                     "value-changed", G_CALLBACK(cb_out_width_changed), NULL);
                     
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "spinbutton_out_height")),
                     "value-changed", G_CALLBACK(cb_out_height_changed), NULL);
    
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "checkbutton_button1")), "toggled",
                 G_CALLBACK(cb_but_toggle1), NULL);
                 
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "checkbutton_button2")), "toggled",
                 G_CALLBACK(cb_but_toggle2), NULL);
                 
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "checkbutton_button3")), "toggled",
                 G_CALLBACK(cb_but_toggle3), NULL);
                 
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "checkbutton_button4")), "toggled",
                 G_CALLBACK(cb_but_toggle4), NULL);
                 
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "checkbutton_button5")), "toggled",
                 G_CALLBACK(cb_but_toggle5), NULL);
    
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "spinbutton_out_ondelay")), "changed",
                 G_CALLBACK(cb_out_ondelay_changed), NULL);
    
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "spinbutton_out_offdelay")), "changed",
                 G_CALLBACK(cb_out_offdelay_changed), NULL);    
    
        
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "button_sensor_add")), "clicked",
                 G_CALLBACK(cb_sensor_add), NULL);   
                 
    g_signal_connect(G_OBJECT
                 (glade_xml_get_widget
                  (gui_get_xml(), "button_sensor_remove")), "clicked",
                 G_CALLBACK(cb_sensor_remove), NULL);   
                 
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "entry_out_exe")), "activate",
                     G_CALLBACK(cb_out_program_changed), NULL);
                     
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "entry_out_exe")), "changed",
                     G_CALLBACK(cb_out_program_changed), NULL);
                     
    g_signal_connect(G_OBJECT
                     (glade_xml_get_widget
                      (gui_get_xml(), "entry_out_exe")),
                     "focus-out-event",
                     G_CALLBACK(cb_out_program_changed), NULL);*/
                     
    sensor_pulldown_refresh();
    sensor_gui_update();
    
    return 0;
}



/**
 * get key-string from combo-box number
 */
char *sensor_key_string(int menu_entry)
{
    
    char *r = NULL;
    gint active;
    GtkComboBox *b;
    
    
    _VERBOSE2 printf("%s()\n", __func__);
    
    if((b = GTK_COMBO_BOX(glade_xml_get_widget(
                    gui_get_xml(), "combobox_out_key"))))
    {
        /* quick & dirty get the n'th entry of a GtkComboBox */
        active = gtk_combo_box_get_active(b);
        gtk_combo_box_set_active(b, menu_entry);
        r = gtk_combo_box_get_active_text(b);
        gtk_combo_box_set_active(b, active);
    }
    
    return r;
}
/** 
 * @} 
 */
